package com.zw.cloud.influxdb.controller;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

import com.zw.cloud.common.utils.DateTimeUtils;
import com.zw.cloud.influxdb.entity.Device;
import com.zw.cloud.influxdb.entity.DeviceVO;
import com.zw.cloud.influxdb.service.InfluxdbQueryService;
import lombok.extern.slf4j.Slf4j;
import org.influxdb.InfluxDB;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@RequestMapping("/influxdb")
public class DeviceRunningReordController {
    @Autowired
    private InfluxdbQueryService influxdbQueryService;

    @Value("${spring.influx.database}")
    private String database;

    // 数据库的表
    private String measurement = "device_report_data_stenter";

    @Autowired
    private InfluxDB influxDBClient;


    /**
     * 插入
     */
    @GetMapping("/insert/{iotCode}")
    //http://localhost:10010/influxdb/insert/dfgs
    public void insert(@PathVariable String iotCode){
        Device device = buildDevice(38f, 66,iotCode,LocalDateTime.now());
        Point point = Point.measurementByPOJO(device.getClass()).addFieldsFromPOJO(device).build();
        influxDBClient.write(point);
    }

    /**
     * 批量插入
     */
    @GetMapping("/batchInsert/{iotCode}/{minusMinutes}")
    //http://localhost:10010/influxdb/batchInsert/dfgs/10
    public void batchInsert(@PathVariable String iotCode,@PathVariable Integer minusMinutes) {
        LocalDateTime now = LocalDateTime.now();
        List<Device> deviceList = new ArrayList<>();
        for (int i = 0; i < minusMinutes; i++) {
            Device device = buildDevice(33f + i, 66,iotCode, now.minusMinutes(i));
            deviceList.add(device);
        }
        deviceList.sort(Comparator.comparing(Device::getTime));
        BatchPoints.Builder builder = BatchPoints.builder();
        deviceList.forEach(m -> builder.point(Point.measurementByPOJO(m.getClass()).addFieldsFromPOJO(m).build()));
        //写入
        influxDBClient.write(builder.build());
    }

    /**
     * 获取数据
     */
    @GetMapping("/queryList/{startTimeStr}/{endTimeStr}/{iotCode}")
    //http://localhost:10010/influxdb/queryList/2024-01-05%2012:00:00/2024-01-11%2014:00:00/dfgs
    public List<DeviceVO> queryList(@PathVariable String startTimeStr,@PathVariable String endTimeStr, @PathVariable String iotCode){
        String sql = "SELECT * FROM device_report_data_stenter where time >= $startTime and time <= $endTime and device=$device and dataType = 'report' order by time asc";
        LocalDateTime startTime = DateTimeUtils.parse2datetime(startTimeStr, DateTimeUtils.DATE_TIME_PATTERN);
        LocalDateTime endTime = DateTimeUtils.parse2datetime(endTimeStr, DateTimeUtils.DATE_TIME_PATTERN);
        Map<String, Object> bindParams = new HashMap<>();
        bindParams.put("startTime", startTime);
        bindParams.put("endTime", endTime);
        bindParams.put("device",iotCode);
        return influxdbQueryService.queryDeviceReportData(sql,DeviceVO.class,bindParams);
    }

    /**
     * 获取数据
     */
    @GetMapping("/query/{page}/{pageSize}/{device}")
    //http://localhost:10010/influxdb/query/1/2/cqk_zy
    public List<DeviceVO> query(@PathVariable Integer page, @PathVariable Integer pageSize, @PathVariable String device){
        // InfluxDB支持分页查询,因此可以设置分页查询条件

        LocalDateTime endTime = LocalDateTime.now();
        LocalDateTime startTime = endTime.minusMinutes(5);
        Map<String, Object> bindParams = new HashMap<>();
        String sql = "SELECT * FROM device_report_data_stenter  where time >= $startTime and time <= $endTime and device=$device and dataType = 'report' order by time asc LIMIT $pageSize OFFSET $startOffSet";
        bindParams.put("startTime", startTime);
        bindParams.put("endTime", endTime);
        bindParams.put("device",device);
        bindParams.put("pageSize", 10);
        bindParams.put("startOffSet", (page - 1) * pageSize);
        log.info("[InfluxdbController][query]sql is {}",sql);
        return influxdbQueryService.queryDeviceReportData(sql,DeviceVO.class,bindParams);
    }

    /**
     * 删除数据
     */
    @GetMapping("/delete")
    //http://localhost:10010/influxdb/delete
    public QueryResult delete(){
        String command = "delete from device_report_data where device='rr' and dataType = 'report' and cycleWindSpeed1 = 75;";
        /**
         * fields not supported in WHERE clause during deletion
         */
        return influxDBClient.query(new Query(command, database));
    }

    /**
     * 批量插入第一种方式
     */
    @GetMapping("/batchInsert1")
    //http://localhost:10010/influxdb/batchInsert1?stop=11
    public void insert(Float stop){
        List<String> lines = new ArrayList<>();
        Long second = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
        Point point = buildingPoint(Float.valueOf(second),stop);
        lines.add(point.lineProtocol());
        //写入
        influxDBClient.write(lines);
    }

    /**
     * 批量插入第2种方式
     */
    @GetMapping("/batchInsert2")
    //http://localhost:10010/influxdb/batchInsert2
    public void batchInsert1(Float stop){
        BatchPoints batchPoints = BatchPoints
                .database(database)
                .consistency(InfluxDB.ConsistencyLevel.ALL)
                .build();
        //遍历sqlserver获取数据
        for(int i = 0;i < 50 ; i++){
            //创建单条数据对象——表名
            Long second = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
            Point point = buildingPoint(Float.valueOf(second),stop);
            //将单条数据存储到集合中
            batchPoints.point(point);
        }
        //批量插入
        influxDBClient.write(batchPoints);
    }

    private Point buildingPoint(Float second,Float stop){
        return Point.measurement(measurement)
                .addField("rtime", second)
                .addField("ctime", second)
                .addField("messageType", 1f)
                .addField("eventCode", 8830f)
                .addField("speed", stop)
                .addField("speedSetting", stop)
                .addField("dryingRoomPresetTemp1", 121f)
                .addField("dryingRoomPresetTemp2", 121f)
                .addField("dryingRoomPresetTemp3", 121f)
                .addField("dryingRoomPresetTemp5", 121f)
                .addField("dryingRoomPresetTemp6", 121f)
                .addField("dryingRoomPresetTemp7", 121f)
                .addField("dryingRoomPresetTemp8", 121f)
                .addField("dryingRoomPresetTemp9", 121f)
                .addField("dryingRoomPresetTemp10", 121f)
                .addField("speciWindSpeed1", 78f)
                .addField("speciWindSpeed2", 78f)
                .addField("speciWindSpeed3", 78f)
                .addField("speciWindSpeed4", 78f)
                .addField("speciWindSpeed5", 78f)
                .addField("speciWindSpeed6", 78f)
                .addField("speciWindSpeed7", 78f)
                .addField("speciWindSpeed8", 78f)
                .addField("speciWindSpeed9", 78f)
                .addField("windSpeed1", 78f)
                .addField("windSpeed2", 99f)
                .addField("windSpeed3", 99f)
                .addField("windSpeed4", 99f)
                .addField("windSpeed5", 99f)
                .addField("windSpeed6", 99f)
                .addField("windSpeed7", 99f)
                .addField("windSpeed8", 99f)
                .addField("windSpeed9", 99f)
                .addField("dataType","report")
                .build();
    }
    private Device buildDevice(Float value, Integer stop,String iotCode,LocalDateTime localDateTime){
        Device device = new Device();
        
        Long second = localDateTime.toEpochSecond(ZoneOffset.of("+8"));
        Instant instant = Instant.ofEpochSecond(second);
        device.setTime(instant);
        device.setRtime(Float.valueOf(String.valueOf(second)));
        device.setCtime(Float.valueOf(String.valueOf(second)));
        device.setMessageType(1f);
        device.setEventCode(8830f);
        device.setSpeedSetting(value);
        device.setSpeed(value);
        device.setInClothTension(value);
        device.setOutClothTension(value);
        device.setRollingCarLiquidLevel(value);
        device.setDryingRoomPresetTemp1(value);
        device.setDryingRoomActualTemp1(value);
        device.setDryingRoomPresetTemp2(value);
        device.setDryingRoomActualTemp2(value);
        device.setDryingRoomPresetTemp3(value);
        device.setDryingRoomActualTemp3(value);
        device.setDryingRoomPresetTemp4(value);
        device.setDryingRoomActualTemp4(value);
        device.setDryingRoomPresetTemp5(value);
        device.setDryingRoomActualTemp5(value);
        device.setDryingRoomPresetTemp6(value);
        device.setDryingRoomActualTemp6(value);
        device.setDryingRoomPresetTemp7(value);
        device.setDryingRoomActualTemp7(value);
        device.setDryingRoomPresetTemp8(value);
        device.setDryingRoomActualTemp8(value);
        device.setDryingRoomPresetTemp9(value);
        device.setDryingRoomActualTemp9(value);
        device.setTotalAmplitude(value);
        device.setDryingRoomDoorWidth(value);
        device.setTopFeed(value);
        device.setLowerFeed(value);
        device.setLeftBrushFeed(value);
        device.setRightBrushFeed(value);
        device.setInClothFeed(value);
        device.setOutClothFeed(value);
        device.setFallingFeed(value);
        device.setSwingFeed(value);
        device.setSpeciWindSpeed1(value);
        device.setWindSpeed1(value);
        device.setSpeciWindSpeed2(value);
        device.setWindSpeed2(value);
        device.setSpeciWindSpeed3(value);
        device.setWindSpeed3(value);
        device.setSpeciWindSpeed4(value);
        device.setWindSpeed4(value);
        device.setSpeciCycleWindSpeed1(value);
        device.setCycleWindSpeed1(value);
        device.setSpeciCycleWindSpeed2(value);
        device.setCycleWindSpeed2(value);
        device.setSpeciCycleWindSpeed3(value);
        device.setCycleWindSpeed3(value);
        device.setSpeciCycleWindSpeed4(value);
        device.setCycleWindSpeed4(value);
        device.setSpeciCycleWindSpeed5(value);
        device.setCycleWindSpeed5(value);
        device.setSpeciCycleWindSpeed6(value);
        device.setCycleWindSpeed6(value);
        device.setSpeciCycleWindSpeed7(value);
        device.setCycleWindSpeed7(value);
        device.setSpeciCycleWindSpeed8(value);
        device.setCycleWindSpeed8(value);
        device.setSpeciCycleWindSpeed9(value);
        device.setCycleWindSpeed9(value);
        device.setTroughTemp(value);
        device.setStopSignal((float)stop);

        device.setSpeciWindSpeed5(value);
        device.setWindSpeed5(value);
        device.setSpeciWindSpeed6(value);
        device.setWindSpeed6(value);
        device.setDryingRoomPresetTemp10(value);
        device.setDryingRoomActualTemp10(value);
        device.setSpeciCycleWindSpeed10(value);
        device.setCycleWindSpeed10(value);

        device.setDryingRoomPresetTemp11(value);
        device.setDryingRoomActualTemp11(value);
        device.setDryingRoomPresetTemp12(value);
        device.setDryingRoomActualTemp12(value);
        device.setSpeciCycleWindSpeed11(value);
        device.setCycleWindSpeed11(value);
        device.setSpeciCycleWindSpeed12(value);
        device.setCycleWindSpeed12(value);
        device.setSpeciCycleWindSpeedSetting(value);
        device.setSpeciWindSpeed8(value);
        device.setWindSpeed8(value);
        device.setNeedleOverfeeding(value);
        device.setOverfeedOfClothDeliveryRoller(value);
        device.setClothGuideBeltOverfeed(value);
        device.setAllDoorWidthSetting(value);
        device.setTotalDoorWidthSetting(value);
        device.setFrontDoorWidthSetting(value);
        device.setFrontDoorWidthActual(value);
        device.setRearDoorWidthSetting(value);
        device.setRearDoorWidthActual(value);
        device.setDoorWidthSetting1(value);
        device.setDoorWidthActual1(value);
        device.setDoorWidthSetting2(value);
        device.setDoorWidthActual2(value);
        device.setDoorWidthSetting3(value);
        device.setDoorWidthActual3(value);
        device.setDoorWidthSetting4(value);
        device.setDoorWidthActual4(value);
        device.setDoorWidthSetting5(value);
        device.setDoorWidthActual5(value);
        device.setDoorWidthSetting6(value);
        device.setDoorWidthActual6(value);
        device.setDoorWidthSetting7(value);
        device.setDoorWidthActual7(value);
        device.setDoorWidthSetting8(value);
        device.setDoorWidthActual8(value);
        device.setDoorWidthSetting9(value);
        device.setDoorWidthActual9(value);
        device.setDoorWidthSetting10(value);
        device.setDoorWidthActual10(value);
        device.setDoorWidthSetting11(value);
        device.setDoorWidthActual11(value);
        device.setDoorWidthSetting12(value);
        device.setDoorWidthActual12(value);
        device.setUpperSuperSpeed(value);
        device.setDownSuperSpeed(value);
        device.setLeftBrushSpeed(value);
        device.setRightBrushSpeed(value);
        device.setPublishingSpeed(value);
        device.setDroppingSpeed(value);
        device.setSwingSpeed(value);
        device.setQuickTapeSpeed(value);
        device.setRollingSpeed(value);
        
        device.setDataType("report");
        device.setDevice(iotCode);
        return device ;
    }

}
